﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CollectionExtensionsTests.cs" company="JDML Consulting Ltd.">
//   Copyright 2011 Photon Project - http://photon.codeplex.com
// </copyright>
// <summary>
//   Defines the CollectionExtensionsTests type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Photon.Collections
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Testing;

    [TestClass]
    public class CollectionExtensionsTests
    {
        [TestMethod]
        public void When_Remove_All_If_IList_Should_Remove_Matches()
        {
            IList<int> collection = new Collection<int>();
            collection.AddRange(GenerateNumberSequence(5));
            TestRemoveAll(collection, x => x % 2 == 0, 1, 3);
        }

        [TestMethod]
        public void When_Remove_All_If_IList_And_Is_Empty_Should_Do_Nothing()
        {
            IList<int> collection = new Collection<int>();
            TestRemoveAll(collection, x => true, new int[0]);
        }

        [TestMethod]
        public void When_Remove_All_If_IList_And_No_Matches_Should_Do_Nothing()
        {
            IList<int> collection = new Collection<int>();
            collection.AddRange(GenerateNumberSequence(5));
            TestRemoveAll(collection, x => x > 4, GenerateNumberSequence(5));
        }

        [TestMethod]
        public void When_Remove_All_If_List_Should_Remove_Matches()
        {
            var list = new List<int>(GenerateNumberSequence(5));
            TestRemoveAll(list, x => x % 2 == 0, 1, 3);
        }

        [TestMethod]
        public void When_Remove_All_If_List_And_Is_Empty_Should_Do_Nothing()
        {
            var list = new List<int>();
            TestRemoveAll(list, x => true, new int[0]);
        }

        [TestMethod]
        public void When_Remove_All_If_List_And_No_Matches_Should_Do_Nothing()
        {
            var sequence = GenerateNumberSequence(5);
            var list = new List<int>(sequence);
            TestRemoveAll(list, x => x > 4, sequence);
        }

        /// <summary>
        ///   Helper method for testing <see cref="CollectionExtensions.RemoveAll{T}" />
        /// </summary>
        /// <typeparam name="TList"> The type of the list. </typeparam>
        /// <typeparam name="TItem"> The type of the list item. </typeparam>
        /// <param name="list"> The list to test. </param>
        /// <param name="match"> The match predicate to use when calling the <see cref="CollectionExtensions.RemoveAll{T}" /> method. </param>
        /// <param name="expected"> The expected contents of the list after calling the <see
        ///    cref="CollectionExtensions.RemoveAll{T}" /> method. </param>
        private static void TestRemoveAll<TList, TItem>(TList list, Predicate<TItem> match, params TItem[] expected)
            where TList : IList<TItem>
        {
            TestRemoveAll(list, match, (IList<TItem>)expected);
        }

        /// <summary>
        ///   Helper method for testing <see cref="CollectionExtensions.RemoveAll{T}" />
        /// </summary>
        /// <typeparam name="TList"> The type of the list. </typeparam>
        /// <typeparam name="TItem"> The type of the list item. </typeparam>
        /// <param name="list"> The list to test. </param>
        /// <param name="match"> The match predicate to use when calling the <see cref="CollectionExtensions.RemoveAll{T}" /> method. </param>
        /// <param name="expected"> The expected contents of the list after calling the <see
        ///    cref="CollectionExtensions.RemoveAll{T}" /> method. </param>
        private static void TestRemoveAll<TList, TItem>(TList list, Predicate<TItem> match, IList<TItem> expected)
            where TList : IList<TItem>
        {
            var originalCount = list.Count;
            Assert.AreEqual(originalCount - expected.Count, list.RemoveAll(match));
            Assert.AreEqual(expected.Count, list.Count);
            ListAssert.AreEqual(expected, list);
        }

        /// <summary>
        ///   Generates a number sequence from <c>0..size - 1</c> .
        /// </summary>
        /// <param name="size"> The size of the number sequence. </param>
        /// <returns> A <see cref="ReadOnlyCollection{Int32}" /> containing the number sequence.\ </returns>
        private static ReadOnlyCollection<int> GenerateNumberSequence(int size)
        {
            var list = new List<int>(size);
            for (var i = 0; i < size; i++)
            {
                list.Add(i);
            }

            return list.AsReadOnly();
        }
    }
}
